package com.bluexmicro.bluetooth.scan

import android.annotation.SuppressLint
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import com.bluexmicro.bluetooth.model.ScanMode
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlin.coroutines.cancellation.CancellationException

interface IScanner {

    val isScanning: StateFlow<Boolean>
    val bluetoothError: StateFlow<Boolean>

    fun scanForPeripherals(context: Context, scanMode: ScanMode)

    fun stopScan()


    fun fetchScanResults(expiredTimeSeconds: Long): List<ScanResult>

    fun clearCache()

}


@Deprecated("")
@SuppressLint("MissingPermission")
fun scanPeripheral(
    context: Context,
    scanMode: Int = ScanSettings.SCAN_MODE_LOW_LATENCY,
) = callbackFlow {
    val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
    val bluetoothAdapter = manager?.adapter
    val scanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            trySend(result)
        }

        override fun onBatchScanResults(results: MutableList<ScanResult>) {
            for (result in results) {
                trySend(result)
            }
        }

        override fun onScanFailed(errorCode: Int) {

            val exception = IllegalStateException("Scan Failed (errorCode: $errorCode)")
            cancel(CancellationException(exception.message, exception))
        }
    }
    val scanner: BluetoothLeScanner? = if (bluetoothAdapter == null) {
        val exception = IllegalStateException("Bluetooth Exception(maybe Bluetooth disable)")
        cancel(CancellationException(exception.message, exception))
        null
    } else {
        val scanner = bluetoothAdapter.bluetoothLeScanner
        val scanSettings = ScanSettings.Builder()
            .setScanMode(scanMode)
            .setReportDelay(0) //如果reportDelay>0的话，第一次report太慢了
            .build()
        scanner?.startScan(null, scanSettings, scanCallback)
        scanner
    }
    awaitClose {
        scanner?.stopScan(scanCallback)
    }
}

